#define DEBUG
#include <cstdio>
#define MAXP 400000
#define MAXNM 1000000

using namespace std;

int min(int a, int b) {
  return a<b ? a : b;
}

int max(int a, int b) {
  return a>b ? a : b;
}

class Side {
public:
  int p, l, r;

  static void sort(Side *a, int l, int r) {
    int i=l, j=r, mid=a[(l+r)/2].p;
    Side temp;
    for (; i<=j; ) {
      for (; a[j].p>mid; j--);
      for (; a[i].p<mid; i++);
      if (i<=j) {
	temp=a[i], a[i]=a[j], a[j]=temp;
	i++, j--;
      }
    }
    if (i<r) {
      sort(a, i, r);
    }
    if (j>l) {
      sort(a, l, j);
    }
  }
};

class SegmentTree {
public:
  int left[MAXNM*4+1], right[MAXNM*4+1], len[MAXNM*4+1], mark[MAXNM*4+1];

  void init(int o, int l, int r) {
    if (l!=r) {
      int mid=(l+r)/2;
      init(o*2, l, mid);
      init(o*2+1, mid+1, r);
    }
    left[o]=right[o]=len[o]=r-l+1;
    mark[o]=0;
  }

  void add(int o, int l, int r, int tl, int tr, int tv) {
    int mid=(l+r)/2;
    if (l==tl && r==tr) {
      mark[o] += tv;
      if (mark[o]) {
	left[o]=right[o]=len[o]=0;
      } else {
	if (l!=r) {
	  if (left[o*2]==mid-l+1) {
	    left[o] = left[o*2]+left[o*2+1];
	  } else {
	    left[o] = left[o*2];
	  }
	  if (right[o*2+1]==r-mid) {
	    right[o] = right[o*2]+right[o*2+1];
	  } else {
	    right[o] = right[o*2+1];
	  }
	  len[o] = max(right[o*2]+left[o*2+1], max(len[o*2], len[o*2+1]));
	} else {
	  left[o]=right[o]=len[o]=1;
	}
      }
    } else {
      if (tl<=mid && tr>=l) {
	add(o*2, l, mid, max(tl, l), min(tr, mid), tv);
      }
      if (tl<=r && tr>mid) {
	add(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), tv);
      }
      if (!mark[o]) {
	if (left[o*2]==mid-l+1) {
	  left[o] = left[o*2]+left[o*2+1];
	} else {
	  left[o] = left[o*2];
	}
	if (right[o*2+1]==r-mid) {
	  right[o] = right[o*2]+right[o*2+1];
	} else {
	  right[o] = right[o*2+1];
	}
	len[o] = max(right[o*2]+left[o*2+1], max(len[o*2], len[o*2+1]));
      } else {
	left[o]=right[o]=len[o]=0;
      }
    }
  }

  void get(int o, int l, int r, int tl, int tr, int f[3]) {
    if (mark[o]) {
      f[0]=f[1]=f[2]=0;
      return;
    }
    if (l==tl && r==tr) {
      f[0]=len[o], f[1]=left[o], f[2]=right[o];
    } else {
      int mid=(l+r)/2;
	int temp[2][3];
	if (tl<=mid && tr>mid) {
	  get(o*2, l, mid, max(tl, l), min(tr, mid), temp[0]);
	  get(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), temp[1]);
	  if (temp[0][1]==mid-tl+1) {
	    f[1] = temp[0][1]+temp[1][1];
	  } else {
	    f[1] = temp[0][1];
	  }
	  if (temp[1][2]==tr-mid) {
	    f[2] = temp[0][2]+temp[1][2];
	  } else {
	    f[2]=temp[1][2];
	  }
	  f[0] = max(temp[0][2]+temp[1][1], max(temp[0][0], temp[1][0]));
	} else {
	  if (tl<=mid && tr>=l) {
	    get(o*2, l, mid, max(tl, l), min(tr, mid), f);
	  } else if (tl<=r && tr>mid) {
	    get(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), f);
	  }
	}
    }
  }
};

int main() {
#ifdef DEBUG
  freopen("4238.in", "r", stdin);
  freopen("4238.out", "w", stdout);
#endif

  static Side side[2][MAXP+1];
  int n, m, p;
  scanf("%d %d %d", &n, &m, &p);
  for (int i=1; i<=p; i++) {
    int x1, y1, x2, y2;
    scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
    side[0][i].p=y1, side[0][i].l=x1, side[0][i].r=x2;
    side[1][i].p=y2, side[1][i].l=x1, side[1][i].r=x2;
  }
  Side::sort(side[0], 1, p);
  Side::sort(side[1], 1, p);

  static SegmentTree sgt;
  sgt.init(1, 1, n);
  int ans=0;
  for (int l=1, r=1, x=1, y=1; l<m || r<m; ) {
    static int temp[3];
    for (; x<=p && side[1][x].p<l; x++) {
      sgt.add(1, 1, n, side[1][x].l, side[1][x].r, -1);
    }
    for (; y<=p && side[0][y].p<=r; y++) {
      sgt.add(1, 1, n, side[0][y].l, side[0][y].r, 1);
    }
    sgt.get(1, 1, n, 1, n, temp);
    ans = max(ans, min(r-l+1, temp[0]));
    if (temp[0]>r-l+1 && r<m) {
      r++;
    } else {
      l++;
    }
  }

  printf("%d", ans);

  fcloseall();
  return 0;
}
